package net.yxsoft.kit;

import com.jfinal.kit.Ret;
import net.yxsoft.resource.PathRes;
import rapid.core.TResult;
import rapid.util.DateKit;
import rapid.util.ImageKit;

import java.io.*;
import java.util.HashSet;
import java.util.Set;

/**
 * @author zhaohaibo
 */
public class ImageUploadKit {


  /**
   * 上传图片允许的最大尺寸，目前只允许 1M
   */
  public static final int MAX_SIZE = 1048576;

  /**
   * 每个子目录允许存 5000 个文件
   */
  public static final int SUB_DIR_MAX_FILES = 5000;

  /**
   * 上传图片临时目录，相对于 baseUploadPath 的路径，是否以 "/" 并无影响
   * 本项目的 baseUploadLoad 为 /var/www/project_name/upload
   */
  public static final String TEMP_PATH = "/img/temp";

  /**
   * 相对于 webRootPath 之后的目录，与"/upload" 是与 baseUploadPath 重合的部分
   */
  private static final String BASE_PATH = "/upload/img/";

  public static final String PATH_COMMON = "common";

  public static String root = "files";

  // 用户前端传入非法参数引发安全问题
  @SuppressWarnings("serial")
  private static final Set<String> allowCategories = new HashSet<String>() {{
    add(PATH_COMMON);
  }};

  /**
   * @param path
   */
  private static String buildPathAndFileName(String path, String extName) {
    return generateFileName(path, extName);
  }

  /**
   * 生成规范的文件名
   * uploadType_年月日时分秒.jpg
   * 图片中添加一些 meta 信息：cover_201604161359.jpg
   */
  private static String generateFileName(String path, String extName) {
    return new StringBuilder()
        .append(root)
        .append("/")
        .append(path)
        .append("/")
        .append(path)
        .append("_")
        .append(DateKit.getDateByTime())
        .append(extName).toString();
  }

  /**
   * 检查 ueditor 上传图片的合法性，返回值格式需要符合 ueditor 的要求
   */
  private static TResult checkUeditorUploadFile(File file) {
    if (file == null) {
      return TResult.fail("无可上传的文件");
    }
    if (ImageKit.notImageExtName(file.getName())) {
      file.delete();      // 非图片类型，立即删除，避免浪费磁盘空间
      return TResult.fail("只支持 jpg、jpeg、png、bmp 四种图片类型");
    }
    if (file.length() > MAX_SIZE * 5) {
      file.delete();      // 图片大小超出范围，立即删除，避免浪费磁盘空间
      return TResult.fail("图片尺寸只允许 5M 大小");
    }
    return TResult.success();
  }

  private static void check(String path) {
    if (!allowCategories.contains(path)) {
      throw new IllegalArgumentException("文件目录不正确");
    }
  }

  public static TResult upload(File file) {
    return upload(PATH_COMMON, file, false);
  }

  public static TResult upload(File file, boolean checkPath) {
    return upload(PATH_COMMON, file, checkPath);
  }

  public static TResult upload(String path, File file) {
    return upload(path, file, false);
  }

  public static TResult upload(String path, File file, boolean checkPath) {
    TResult rs = checkUeditorUploadFile(file);
    if (rs.isFail()) {
      return rs;
    }
    String fileSize = file.length() + "";
    String extName = "." + ImageKit.getExtName(file.getName());

    if (checkPath) {
      check(path);
    }

    String fileName = buildPathAndFileName(path, extName);
    return TResult.success().data(fileName);

  }

  public static Ret uploadContent(String path, File file) {

    TResult rs = checkUeditorUploadFile(file);
    if (rs.isFail()) {
      return Ret.create("errno", 1).set("data", "上传出错");
    }

    String fileName = "/" + root + "/" + file.getName();

    String[] fileNames = new String[1];
    fileNames[0] = fileName;

    return Ret.create("errno", 0).set("data", fileNames);

  }


  /**
   * @Title: byteToFile
   * @Description: 把二进制数据转成指定后缀名的文件，例如PDF，PNG等
   * @param contents 二进制数据
   * @param filePath 文件存放目录，包括文件名及其后缀，如D:\file\bike.jpg
   * @Author: Wiener
   * @Time: 2018-08-26 08:43:36
   */
  public static void byteToFile(byte[] contents, String filePath) {
    BufferedInputStream bis = null;
    FileOutputStream fos = null;
    BufferedOutputStream output = null;
    try {
      ByteArrayInputStream byteInputStream = new ByteArrayInputStream(contents);
      bis = new BufferedInputStream(byteInputStream);
      File file = new File(filePath);
      // 获取文件的父路径字符串
      File path = file.getParentFile();
      if (!path.exists()) {

        boolean isCreated = path.mkdirs();
        if (!isCreated) {

        }
      }
      fos = new FileOutputStream(file);
      // 实例化OutputString 对象
      output = new BufferedOutputStream(fos);
      byte[] buffer = new byte[1024];
      int length = bis.read(buffer);
      while (length != -1) {
        output.write(buffer, 0, length);
        length = bis.read(buffer);
      }
      output.flush();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        bis.close();
        fos.close();
        output.close();
      } catch (IOException e0) {

      }
    }
  }

}
